package com.qfmy.webapp.service.impl.agent;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.qfmy.model.query.agent.VideoQuery;
import com.qfmy.webapp.service.agent.VideoService;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * 智谱清影文字/图片转视频实现类（适配官方API规范）
 */
@Slf4j
@Service
@SuppressWarnings("all")
public class VideoGenerateServiceImpl implements VideoService {

    /**
     * 智谱API密钥（从配置文件读取）
     */
    @Value("${zhipu.api.key}")
    private String zhipuApiKey;

    /**
     * 智谱清影文生视频API地址（官方最新）
     */
    @Value("${zhipu.video.infer.url:https://api.chatglm.cn/video}")
    private String ZHIPU_INFER_URL;

    /**
     * 智谱清影任务查询API地址
     */
    private static final String ZHIPU_TASK_QUERY_URL = "https://api.chatglm.cn/video/task/";

    /**
     * 请求超时时间（秒）
     */
    private static final int TIMEOUT_SECONDS = 60;

    /**
     * 轮询间隔（秒）- 视频生成需要时间，每5秒查一次
     */
    private static final int POLL_INTERVAL_SECONDS = 5;

    /**
     * 最大轮询次数（避免无限循环）
     */
    private static final int MAX_POLL_TIMES = 20;

    /**
     * 文字/图片转视频核心方法
     * @param videoQuery 请求参数
     * @return 生成的视频URL（临时有效，建议及时下载）
     */
    @Override
    public String textToVideo(VideoQuery videoQuery) {
        // 1. 严格参数校验
        validateParams(videoQuery);

        // 2. 构建OkHttp客户端（单例优化，此处简化为方法内创建）
        OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(TIMEOUT_SECONDS, TimeUnit.SECONDS)
                .readTimeout(TIMEOUT_SECONDS, TimeUnit.SECONDS)
                .writeTimeout(TIMEOUT_SECONDS, TimeUnit.SECONDS)
                .retryOnConnectionFailure(true) // 连接失败重试
                .build();

        try {
            // 3. 提交生成任务，获取taskId
            String taskId = submitGenerateTask(client, videoQuery);
            log.info("视频生成任务提交成功，taskId: {}", taskId);

            // 4. 轮询查询任务状态，直到生成完成/失败/超时
            return pollTaskStatus(client, taskId);

        } catch (Exception e) {
            log.error("视频生成全流程失败", e);
            throw new RuntimeException("视频生成失败：" + e.getMessage(), e);
        }
    }

    /**
     * 参数校验
     */
    private void validateParams(VideoQuery videoQuery) {
        if (videoQuery == null) {
            throw new IllegalArgumentException("请求参数不能为空");
        }
        // 文生视频必须传prompt，图生视频必须传image
        boolean isText2Video = videoQuery.getImage() == null || videoQuery.getImage().trim().isEmpty();
        if (isText2Video && (videoQuery.getPrompt() == null || videoQuery.getPrompt().trim().isEmpty())) {
            throw new IllegalArgumentException("文生视频时提示词(prompt)不能为空");
        }
        if (!isText2Video && (videoQuery.getImage() == null || videoQuery.getImage().trim().isEmpty())) {
            throw new IllegalArgumentException("图生视频时图片URL(image)不能为空");
        }
        // 分辨率校验（免费版仅支持1440x960，超出则强制修正）
        if (videoQuery.getWidth() != null && videoQuery.getWidth() != 1440) {
            log.warn("免费版仅支持1440x960分辨率，自动修正width为1440");
            videoQuery.setWidth(1440);
        }
        if (videoQuery.getHeight() != null && videoQuery.getHeight() != 960) {
            log.warn("免费版仅支持1440x960分辨率，自动修正height为960");
            videoQuery.setHeight(960);
        }
    }

    /**
     * 提交生成任务，获取taskId
     */
    private String submitGenerateTask(OkHttpClient client, VideoQuery videoQuery) throws IOException {
        // 构建请求参数
        JSONObject requestBody = buildRequestParams(videoQuery);
        log.info("提交视频生成任务，参数: {}", requestBody);

        // 构建HTTP请求
        Request request = new Request.Builder()
                .url(ZHIPU_INFER_URL)
                .header("Authorization", "Bearer " + zhipuApiKey)
                .header("Content-Type", "application/json;charset=utf-8")
                .post(RequestBody.create(
                        requestBody.toJSONString(),
                        MediaType.parse("application/json;charset=utf-8")
                ))
                .build();

        // 发送请求
        try (Response response = client.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                String errorMsg = response.body() != null ? response.body().string() : "无错误信息";
                throw new IOException("提交生成任务失败，状态码：" + response.code() + "，错误信息：" + errorMsg);
            }

            // 解析响应获取taskId
            String responseBody = response.body().string();
            JSONObject resultJson = JSON.parseObject(responseBody);
            if (!"success".equals(resultJson.getString("status"))) {
                throw new RuntimeException("任务提交失败：" + resultJson.getString("msg"));
            }
            String taskId = resultJson.getJSONObject("data").getString("task_id");
            if (taskId == null || taskId.trim().isEmpty()) {
                throw new RuntimeException("响应中未获取到有效taskId，响应内容：" + responseBody);
            }
            return taskId;
        }
    }

    /**
     * 轮询查询任务状态
     */
    private String pollTaskStatus(OkHttpClient client, String taskId) throws InterruptedException, IOException {
        int pollCount = 0;
        while (pollCount < MAX_POLL_TIMES) {
            pollCount++;
            log.info("第{}次轮询任务状态，taskId: {}", pollCount, taskId);

            // 构建查询请求
            Request request = new Request.Builder()
                    .url(ZHIPU_TASK_QUERY_URL + taskId)
                    .header("Authorization", "Bearer " + zhipuApiKey)
                    .header("Content-Type", "application/json;charset=utf-8")
                    .get()
                    .build();

            try (Response response = client.newCall(request).execute()) {
                if (!response.isSuccessful()) {
                    log.error("查询任务状态失败，状态码：{}", response.code());
                    Thread.sleep(POLL_INTERVAL_SECONDS * 1000);
                    continue;
                }

                // 解析状态响应
                String responseBody = response.body().string();
                JSONObject resultJson = JSON.parseObject(responseBody);
                JSONObject data = resultJson.getJSONObject("data");
                String status = data.getString("status");

                switch (status) {
                    case "succeeded": // 生成成功
                        String videoUrl = data.getString("video_url");
                        if (videoUrl == null || videoUrl.trim().isEmpty()) {
                            throw new RuntimeException("任务成功但未返回视频URL，响应：" + responseBody);
                        }
                        log.info("视频生成成功，URL: {}", videoUrl);
                        return videoUrl;
                    case "failed": // 生成失败
                        String failMsg = data.getString("msg");
                        throw new RuntimeException("视频生成失败：" + failMsg);
                    case "processing": // 生成中
                        Integer progress = data.getInteger("progress");
                        log.info("视频生成中，进度：{}%", progress == null ? "未知" : progress);
                        break;
                    default: // 其他状态（如pending）
                        log.info("任务状态：{}，等待中...", status);
                }
            }

            // 等待轮询间隔
            Thread.sleep(POLL_INTERVAL_SECONDS * 1000);
        }

        // 轮询超时
        throw new RuntimeException("视频生成超时（超过" + (MAX_POLL_TIMES * POLL_INTERVAL_SECONDS) + "秒），请稍后重试");
    }

    /**
     * 构建智谱清影API的请求参数（适配官方最新规范）
     */
    @NotNull
    private JSONObject buildRequestParams(@NotNull VideoQuery videoQuery) {
        JSONObject params = new JSONObject();
        String finalPrompt = videoQuery.getPrompt() == null ? "" : videoQuery.getPrompt().trim();

        // 1. 处理风格/灵感参数（增强提示词）
        if (videoQuery.getStyle() != null && !videoQuery.getStyle().trim().isEmpty()) {
            finalPrompt += "，风格：" + videoQuery.getStyle().trim();
        }
        if (Boolean.TRUE.equals(videoQuery.getInspiration())) {
            finalPrompt += "，画面富有创意和艺术感，细节丰富，色彩协调，构图美观，电影级画质";
        }

        // 2. 基础参数（官方固定模型）
        params.put("model", "cogvideox-2b"); // 免费版固定使用cogvideox-2b

        // 3. 区分文生视频/图生视频
        boolean isText2Video = videoQuery.getImage() == null || videoQuery.getImage().trim().isEmpty();
        if (isText2Video) {
            // 文生视频核心参数
            params.put("prompt", finalPrompt); // 提示词
        } else {
            // 图生视频核心参数
            params.put("image", videoQuery.getImage().trim()); // 图片URL
            if (!finalPrompt.isEmpty()) {
                params.put("prompt", finalPrompt); // 补充描述
            }
        }

        // 4. 视频基础配置（免费版固定参数）
        JSONObject parameters = new JSONObject();
        parameters.put("duration", 6); // 免费版固定6秒
        parameters.put("resolution", "1440x960"); // 免费版固定分辨率
        parameters.put("generate_audio", videoQuery.getAddMusic() == null ? false : videoQuery.getAddMusic()); // 是否生成背景音乐
        parameters.put("fps", 16); // 免费版默认16fps（官方优化值）

        params.put("parameters", parameters);
        return params;
    }
}